package com.ihome.excel.xlsx.engine.export;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.ihome.excel.xlsx.config.ExcelRuleConfig;
import com.ihome.excel.xlsx.entity.EncapsulationEnum;
import com.ihome.excel.xlsx.entity.ExcelRule;
import com.ihome.excel.xlsx.exceptions.ExcelRuleValidateException;
import com.ihome.excel.xlsx.exceptions.ExcelWriteException;
import com.ihome.excel.xlsx.exceptions.ThrowableDefine;

public class ExcelWriteEngine {

	private static final String GET = "get";

	private ExcelRuleValidate excelRuleValidate = new ExcelRuleValidate();

	private CellWriteEngine cellWriteEngine = new CellWriteEngine();
	
	private SheetWriteEngine sheetWriteEngine = new SheetWriteEngine();

	private String ruleName;

	public ExcelWriteEngine(String ruleName) {
		this.ruleName = ruleName;
	}
	
	public Sheet createSheet(Workbook wb) {
		if(wb == null) {
			throw ThrowableDefine.PARAMETER_VALIDATE_EXP.getIllegaArgumentExp("wb");
		}
		ExcelRule excelRule = ExcelRuleConfig.getExcelRule(ruleName);
		if(excelRule == null) {
			throw ThrowableDefine.EXCEL_RULE_NOT_EXISTS.getExcelWriteException(ruleName);
		}
		try {
			excelRuleValidate.checkExcelRule(excelRule);
		} catch (ExcelRuleValidateException e) {
			throw new ExcelWriteException(e.getMessage());
		}
		Sheet sheet = sheetWriteEngine.createSheet(wb, excelRule);
		return sheet;
	}

	public void write(Workbook wb,Sheet sheet, int rowIndex, List rowsCollection) {
		if(wb == null) {
			throw ThrowableDefine.PARAMETER_VALIDATE_EXP.getIllegaArgumentExp("wb");
		}
		if(sheet == null) {
			throw ThrowableDefine.PARAMETER_VALIDATE_EXP.getIllegaArgumentExp("sheet");
		}
		if(rowsCollection == null || rowsCollection.isEmpty()) {
			throw ThrowableDefine.PARAMETER_VALIDATE_EXP.getIllegaArgumentExp("rowsCollection");
		}
		ExcelRule excelRule = ExcelRuleConfig.getExcelRule(ruleName);
		Row row = null;
		Cell cell = null;
		int columnAttributeTotalCount  = excelRule.getColumnAttributeNameConfig().size();
		Method[] methods = null;
		if (!EncapsulationEnum.MAP.toString().equals(excelRule.getClassName())) {
			try {
				methods = Class.forName(excelRule.getClassName()).getDeclaredMethods();
			} catch (SecurityException e) {
				throw new ExcelWriteException(e.getMessage());
			} catch (ClassNotFoundException e) {
				throw new ExcelWriteException(e.getMessage());
			}
		}
		/**
		 * 如果rowIndex == 1 说明本次是第一批次的写入 此时将写入列头
		 */
		if (rowIndex == 1) {
			row = sheet.createRow(rowIndex - 1);
			int columnTotalCount = excelRule.getColumnHeadNameConfig().size();
			for (int i = 0; i < columnTotalCount; i++) {
				cell = row.createCell(i);
				cell.setCellValue(excelRule.getColumnHeadNameConfig().get(i).getName());
			}
		}
		int rowsCollectionSize = rowsCollection.size();
		String attributeName;
		String methodName;
		Object obj;
		Map map;
		Object value = null;
		for (int i = 0; i < rowsCollectionSize; i++) {
			row = sheet.createRow(rowIndex + i);
			for (int j = 0; j < columnAttributeTotalCount; j++) {
				attributeName = excelRule.getColumnAttributeNameConfig().get(j);
				cell = row.createCell(j);
				obj = rowsCollection.get(i);
				if (EncapsulationEnum.MAP.toString().equals(excelRule.getClassName())) {
					map = (Map) obj;
					value = map.get(attributeName);
				} else {
					methodName = GET + attributeName.substring(0, 1).toUpperCase() + attributeName.substring(1, attributeName.length());
					try {
						for (Method md : methods) {
							if (md.getName().equals(methodName)) {
								value = md.invoke(obj, null);
								break;
							}
						}
					} catch (Exception e) {
						throw new ExcelWriteException(e);
					}					
				}
				cellWriteEngine.writeCellValue(cell, value);
			}
		}
	}
}
